package com.easylinkin.linkappapi.deviceattributestatus.controller;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.easylinkin.linkappapi.common.exceptions.BusinessException;
import com.easylinkin.linkappapi.common.model.RequestModel;
import com.easylinkin.linkappapi.common.utils.DateUtil;
import com.easylinkin.linkappapi.device.entity.Device;
import com.easylinkin.linkappapi.deviceattributestatus.entity.DeviceAttributeStatus;
import com.easylinkin.linkappapi.deviceattributestatus.service.DeviceAttributeStatusService;
import com.easylinkin.linkappapi.openapi.util.HttpClientUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import jodd.util.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.springframework.scheduling.annotation.Async;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.*;
import site.morn.rest.RestBuilders;
import site.morn.rest.RestMessage;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.nio.charset.Charset;
import java.util.*;

/**
 * @author TongJie
 * @since 2020-04-18
 */
@RestController
@Api(value="设备属性状态控制器",tags={"设备属性状态"})
@RequestMapping("/deviceAttributeStatus")
@Slf4j
public class DeviceAttributeStatusController {

    @Resource
    private DeviceAttributeStatusService service;

    @ApiOperation("设备最新属性分页查询")
    @PostMapping("getPageGlobal")
    public RestMessage getPageGlobal(@RequestBody RequestModel<DeviceAttributeStatus> requestModel) {
        Assert.notNull(requestModel, "参数为空");
        Assert.notNull(requestModel.getPage(), "分页参数为空");
        Assert.notNull(requestModel.getCustomQueryParams(), "参数不完整");
        return RestBuilders.successBuilder().data(service.getPageGlobal(requestModel.getPage(), requestModel.getCustomQueryParams())).build();
    }

    @ApiOperation("设备属性历史数据流水查询")
    @PostMapping("getHistoricDataPageFromEs")
    public RestMessage getHistoricDataPageFromEs(@RequestBody RequestModel<DeviceAttributeStatus> requestModel) {
        Assert.notNull(requestModel, "参数为空");
        Assert.notNull(requestModel.getPage(), "分页参数为空");
        Assert.notNull(requestModel.getCustomQueryParams(), "参数不完整");
        IPage<Map> historicDataFromEs = service.getHistoricDataFromEs(requestModel);
        if (Boolean.TRUE.equals(requestModel.getCustomQueryParams().getGenarateData()) && CollectionUtil.isEmpty(historicDataFromEs.getRecords())) {
            //查找相关属性的最近的一条记录时间，往前推7天,格式为queryTimeEnd ："2024-04-13 09:27:00"     queryTimeStart："2024-03-29 09:27:00"
            Date latestTime = service.getLatestRecordTime(requestModel);
            if (latestTime!=null){
                //因施工云项目es目前并没有进行数据删除，所以这里直接进行数据查询，否则还得判断es中对应时间段索引是否存在
                //日期向前推7天
                Date startTime = DateUtil.addDay(latestTime, -7);
                requestModel.getCustomQueryParams().setQueryTimeStart(DateUtil.format(startTime, DateUtil.DATE_TIME_FORMAT_DEFAULT));
                requestModel.getCustomQueryParams().setQueryTimeEnd(DateUtil.format(latestTime, DateUtil.DATE_TIME_FORMAT_DEFAULT));
                return RestBuilders.successBuilder().data(service.getHistoricDataFromEs(requestModel)).build();
            }

        }
        return RestBuilders.successBuilder().data(historicDataFromEs).build();
    }

    /**
     * todo 测试 待删除
     */
    @GetMapping ("testGetHistoricDataPageFromEs")
    @Async
    public void testGetHistoricDataPageFromEs() {
        while (true) {
            RequestModel requestModel = new RequestModel();
            requestModel.setPage(new Page(1, 100));
            DeviceAttributeStatus cqp = new DeviceAttributeStatus();
            cqp.setDeviceCode("07121603");
            cqp.setDeviceUnitId("92afac6a44199a571472512b4b26fe65");
            cqp.setQueryTimeEnd("2022-08-04 14:47:02");
            cqp.setQueryTimeStart("2022-08-03 14:47:02");
            cqp.setNecessaryFieldList(new ArrayList<>(Collections.singleton("noise")));
            requestModel.setCustomQueryParams(cqp);

            HttpPost httpPost = new HttpPost(
//                    "http://172.16.10.192:16005/api" + "/deviceAttributeStatus/getHistoricDataPageFromEs");
                    "http://127.0.0.1:5042" + "/deviceAttributeStatus/getHistoricDataPageFromEs");
            //添加请求头
            httpPost.addHeader("Content-Type", "application/json");
            //设置接收形式
            httpPost.setHeader("Accept", "*/*");
            httpPost.setHeader("token", "5a920f536428050edddcce5212f36a97");
            //设置授权
//        httpPost.setHeader("Blade-Auth", "bearer " + getAccessTokenTest());
//        httpPost.setHeader("Authorization", "Basic c2FiZXI6c2FiZXJfc2VjcmV0");
            //创建登录实体
            httpPost.setEntity(new StringEntity(JSONObject.toJSONString(requestModel), Charset.forName("UTF-8")));
            log.info("BladeGuardApi request:{}", httpPost);
            String str = HttpClientUtil.doPost(httpPost);
            log.info("定位es偶尔查询数据失败，查询到数据条数为：" + str.substring(0, 120));
            try {
//                休眠 0-n个小时
                Double hoursToMillis = Math.random() * (1000 * 60 * 60 * 1);
                long sleepTime = hoursToMillis.longValue();
                log.info("定位es偶尔查询数据失败，休眠时间为：" + (sleepTime / 1000.0 / 60) + "分钟");
                Thread.sleep(sleepTime);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }

    @ApiOperation("设备历史流水数据导出")
    @PostMapping("exportHistoryExcel")
    public void exportHistoryExcel(@RequestBody DeviceAttributeStatus deviceAttributeStatus, HttpServletRequest request, HttpServletResponse response) {
        try {
            service.exportHistoryExcel(deviceAttributeStatus, request, response);
        } catch (Exception e) {
            response.setHeader("errormessage", e.getMessage());
        }
    }

    @ApiOperation("根据设备编码获取设备属性编码、属性值、属性单位")
    @PostMapping("getProps")
    public RestMessage getProps(@RequestBody DeviceAttributeStatus deviceAttributeStatus) {
        Assert.notNull(deviceAttributeStatus, "参数为空");
        Assert.notNull(deviceAttributeStatus.getDeviceCode(), "设备code为空");

        return RestBuilders.successBuilder().data(service.getProps(deviceAttributeStatus)).build();
    }

    @ApiOperation("设备实时数据")
    @PostMapping("getDeviceRealtimeData")
    public RestMessage getDeviceRealtimeData(@RequestBody DeviceAttributeStatus deviceAttributeStatus) {
        Assert.notNull(deviceAttributeStatus, "参数为空");
        Assert.notNull(deviceAttributeStatus.getDeviceCode(), "设备code为空");
        return RestBuilders.successBuilder().data(service.getDeviceRealtimeData(deviceAttributeStatus)).build();
    }

    /**
     * 通过某指标，查询设备最新属性值
     *
     * @param deviceAttributeStatus
     * @return
     */
    @ApiOperation("通过某指标，查询设备最新属性值")
    @PostMapping("getDeviceRealtimeDataByCertainTag")
    public RestMessage getDeviceRealtimeDataByCertainTag(@RequestBody DeviceAttributeStatus deviceAttributeStatus, @RequestParam(value = "deviceTypeName",required = false) String deviceTypeName) {
        Assert.notNull(deviceAttributeStatus, "参数为空");
        return RestBuilders.successBuilder().data(service.getDeviceRealtimeDataByCertainTag(deviceAttributeStatus,deviceTypeName)).build();
    }

    @ApiOperation("大屏设备实时数据")
    @PostMapping("getDeviceRealtimeDataForBigScreen")
    public RestMessage getDeviceRealtimeDataForBigScreen(@RequestBody Device device) {
        Assert.notNull(device, "参数为空");
        Assert.notNull(device.getCode(), "设备code为空");
        Assert.notNull(device.getDeviceTypeName(), "设备类型为空");
        List<DeviceAttributeStatus> deviceRealtimeDataForBigScreen = service
            .getDeviceRealtimeDataForBigScreen(device);
        //兼容driver_name1
        List<DeviceAttributeStatus> result = new ArrayList<>();
        if(CollectionUtil.isNotEmpty(deviceRealtimeDataForBigScreen)){
            for (int i = 0; i < deviceRealtimeDataForBigScreen.size(); i++) {
                DeviceAttributeStatus status = deviceRealtimeDataForBigScreen.get(i);
                result.add(status);
                if(StringUtil.isNotBlank(status.getPropCode())
                        && "driver_name1".equals(status.getPropCode())){
                    DeviceAttributeStatus status1 = new DeviceAttributeStatus();
                    BeanUtil.copyProperties(status,status1);
                    status1.setPropCode("driver_name");
                    result.add(status1);
                }
            }
        }
        return RestBuilders.successBuilder().data(result).build();
    }

    @ApiOperation("获取设备实时数据（设备型号版本过滤）")
    @PostMapping("getDeviceRealtimeDataNoVersion")
    public RestMessage getDeviceRealtimeDataNoVersion(@RequestBody DeviceAttributeStatus deviceAttributeStatus) {
        Assert.notNull(deviceAttributeStatus, "参数为空");
        Assert.notNull(deviceAttributeStatus.getDeviceCode(), "设备code为空");
        return RestBuilders.successBuilder().data(service.getDeviceRealtimeDataNoVersion(deviceAttributeStatus)).build();
    }

    @ApiOperation("根据父属性编码获取设备实时数据")
    @PostMapping("getDeviceRealtimeDataByParentPropCode")
    public RestMessage getDeviceRealtimeDataByParentPropCode(@RequestBody DeviceAttributeStatus deviceAttributeStatus) {
        Assert.notNull(deviceAttributeStatus, "参数为空");
        Assert.notNull(deviceAttributeStatus.getDeviceCode(), "设备code为空");
        Assert.hasLength(deviceAttributeStatus.getParentPropCode(), "父属性code不能为空");
        return RestBuilders.successBuilder().data(service.getDeviceRealtimeDataByParentPropCode(deviceAttributeStatus)).build();
    }

    /**
     * 这是个空接口！
     * 2021-11-12 查看前端调用此接口的函数未使用
     */
    @PostMapping("getHistoricAttributeStatus")
    public RestMessage getHistoricAttributeStatus(@RequestBody DeviceAttributeStatus deviceAttributeStatus) {
        return RestBuilders.successBuilder().data(null).build();
    }

    @PostMapping("exportData")
    @ApiOperation("设备属性状态导出")
    public void exportData(DeviceAttributeStatus deviceAttributeStatus, HttpServletRequest request, HttpServletResponse response) {
        service.exportData(deviceAttributeStatus, request, response);
    }

    @ApiOperation("获取项目设备状态")
    @PostMapping("/getDeviceDataByProject")
    public RestMessage getDeviceDataByProject(@RequestBody Map<String, String> map) {
        if (StringUtils.isBlank(map.get("projectCode"))) {
            throw new BusinessException("项目编号不能为空");
        }
        if (StringUtils.isBlank(map.get("deviceCode"))) {
            throw new BusinessException("设备编号不能为空");
        }
        List<DeviceAttributeStatus> deviceDataByProject = service.getDeviceDataByProject(map);
        return RestBuilders.successBuilder().data(deviceDataByProject).build();
    }

}
